#include "StdAfx.h"
#include "TokenStream.h" 
#include <iostream>
using namespace std;

CTokenStream::CTokenStream(string input)
{
	m_inputStream = input;
}

CTokenStream::~CTokenStream(void)
{
}

const vector<int> & CTokenStream::tokenaze()
{
	vector<char> separators;
	separators.push_back(' ');
	separators.push_back(')');
	separators.push_back('(');
	separators.push_back(';');

	char c = ' ';
	string str = "";
	for ( int i = 0; i < m_inputStream.size(); i++ )
	{
		c = m_inputStream[i];
		if ( !inArray(separators, c) )
		{
			str += c;
		}
		else
		{
			if( !str.empty() )
			{
				pushString(str);
			}
			pushSeparator(c);
			str = "";
		}
	}	
	if( !str.empty() )
	{
		pushString(str);
	}
	if ( m_outputStream[m_outputStream.size() - 1] != SEMICOLON )
	{
		m_errors.push_back(NO_SEMICOLON);
		m_outputStream.push_back(SEMICOLON);
	}
	echoErrors();
	return m_outputStream;
}

void CTokenStream::echoErrors()
{
	for( int i = 0; i < m_errors.size(); i++ )
	{
		switch (m_errors[i])
		{
		case NO_SEMICOLON:
			cout << "WARNING: no semicolon at the end" << endl;
			break;
		case UNEXPECTED_SYMBOL:
			cout << "WARNING: unexpected symbol in variable" << endl;
			break;
		}
	}
}

void CTokenStream::pushString(const string & str)
{
	if ( str == "while")
	{
		m_outputStream.push_back( REPETITION_WHILE );
	}
	else if ( str == "fly")
	{
		m_outputStream.push_back( COMMAND_FLY );
	}
	else if ( str == "right")
	{
		m_outputStream.push_back( COMMAND_RIGHT );
	}
	else if ( str == "quack")
	{
		m_outputStream.push_back( COMMAND_QUACK );
	}
	else 
	{
		if ( !checkVariable(str) )
		{			
			m_errors.push_back(UNEXPECTED_SYMBOL);
		}
		m_outputStream.push_back( VARIABLE );
		int idPos = checkId(str); //checks is id defined
		if ( idPos != -1 )
		{
			m_outputStream.push_back( idPos );
		}
		else
		{
			m_ids.push_back(str);
			m_outputStream.push_back( m_ids.size() - 1 );
		}
	}
}

void CTokenStream::pushSeparator(char c)
{
	switch (c)
	{
	case ' ':
		//m_outputStream.push_back( WHITE_SPACE );
		break;
	case ')':
		m_outputStream.push_back( RIGHT_PARANTHESIS );
		break;
	case '(':
		m_outputStream.push_back( LEFT_PARANTHESIS );
		break;
	case ';':
		m_outputStream.push_back( SEMICOLON );
		break;
	}
}

bool CTokenStream::inArray(const vector<char> &arr, const char &needle)
{
	bool result = false;
	for ( int i = 0; i < arr.size(); i++ )
	{
		if ( arr[i] == needle )
		{
			result = true;
		}
	}
	return result;
}

int CTokenStream::checkId(const string &id)
{
	int result = -1;
	for ( int i = 0; i < m_ids.size(); i++ )
	{
		if ( m_ids[i] == id )
		{
			result = i;
		}
	}
	return result;
}

bool CTokenStream::checkVariable(const string &variable)
{
	char symbols[52] = {'q','w','e','r','t','y','u','i','o','p','a','s','d','f','g','h','j','k','l','z','x','c','v','b','n','m',
		'Q','W','E','R','T','Y','U','I','O','P','A','S','D','F','G','H','J','K','L','Z','X','C','V','B','N','M'};
	vector<char> symbolsVec(symbols, symbols + 52); 
	bool result = true;
	for ( int i = 0; i < variable.size(); i++ )
	{
		if ( !inArray(symbolsVec, variable[i]) )
		{
			result = false;
		}
	}
	return result;
}
